
// ECMAScript 6 类表面上看起来可以支持正式的面向对象编程，但实际上它背后使用的仍然是原型和构造函数的概念
//1.定义类也有两种主要方式：类声明和类表达式
//2.与函数表达式类似，类表达式在它们被求值前也不能引用。不过，与函数定义不同的是，虽然函数声明可以提升，但类定义不能
//3.另一个跟函数声明不同的地方是，函数受函数作用域限制，而类受块作用域限制
{
  function FunctionDeclaration() { }
  class ClassDeclaration { }
}
console.log(FunctionDeclaration); // FunctionDeclaration() {} // 函数声明，var表达式类型，不受块作用域。let，const的函数表达式受影响
console.log(ClassDeclaration); // ReferenceError: ClassDeclaration is not defined


// class 基本使用

class Person {
  // constructor 中this指实例对象，给实例对象添加属性方法
  constructor(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayHi = function () {
      console.log(this.name);
    }
  }
  // 类块中的函数，表示原型对象中的方法，不能赋值为原始值或对象
  sayName() {
    console.log(this.name)
  }
  // 静态方法，定义在Person上，this指Person，而不是实例对象
  // 需要static关键字，指不需要实例共享的方法
  static sayAge() {
    console.log(this)
  }
}

let p1 = new Person('zhang', 11, 'man')
console.log(p1)
p1.sayName()
Person.sayAge()


// class 继承

class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age
  }
  static sayName() {
    console.log(this);
  }
}
// 特点：
//1.直接使用extends继承父类 class Dog extends Animal{},会继承父类constructor和原型
//2.super关键字，只能在派生类（子类，个人理解）中使用，且仅限于类构造函数（constructor(){}）、实例方法和静态方法内部。
class Dog extends Animal {
  constructor(sex) { // 构造函数中
    super() // 相当于super.constructor()
    this.sex = sex;
  }
  // 实例方法无例子
  static sayName() {// 静态方法中
    super.sayName()
  }
}
//3.不要在调用super前，引用this
class Dog1 extends Animal {
  constructor() {
    this.sex = 1; // 错误
    super()
  }
}
//4.不能单独引用super关键字，要么用它调用构造函数，要么用它引用静态方法。
class Dog2 extends Animal {
  constructor() {
    console.log(super); // 不能单独调用
  }
}
//5.super()行为相当于调用构造函数，如果需要给父类构造函数传参，需要手动传入
class Dog2 extends Animal {
  constructor(name, age) {
    super(name, age)
  }
}
// 6.如果派生类没有定义类构造函数，在实例化派生类时会调用 super()，而且会传入所有传给派生类的参数。
//7.如果在派生类中显式定义了构造函数，则要么必须在其中调用 super()，要么必须在其中返回一个对象。
class Dog3 extends Animal {
  constructor() {
    super()// 必须调用

    // return {}// 或者返回对象
  }
}
//
//